/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package javaapplication1;
/**
 *
 * @author Jorge Ivan Cadavid
 */

import execution.LocalProcessExecutor;
import java.sql.*;
import java.text.ParseException;
import physicalmachine.*;
import java.io.BufferedWriter;
import java.io.IOException;
import java.util.Date;
//import java.io.FileInputStream;
import java.io.FileWriter;
//import java.io.PrintStream;
import java.io.PrintWriter;
//import java.util.Properties;
import java.util.Calendar;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.nsclient4j.NSClient4JException;
import org.hyperic.sigar.Mem;
import org.hyperic.sigar.Cpu;
import org.hyperic.sigar.CpuPerc;
import org.hyperic.sigar.NetInterfaceStat;
import org.hyperic.sigar.Uptime;
import org.hyperic.sigar.SigarException;
import org.hyperic.sigar.cmd.SigarCommandBase;

public class MonitorAgent extends SigarCommandBase {

    private static final String fmt = "MMM dd HH:mm:ss";
    private static final String fmt1 = "ddMMyyyyHHmmss";
    private static boolean continuarMonitoreo;
    private String UUID;
    public int parameter;
    public int contador=0;
    //int ContadorRegistros;
    Date parameter1;
    PrintWriter salida, salida2 = null;
    BufferedWriter bw, bw2 =null;
    FileWriter fw,fw2 =null;
    DatabaseConnection conexionBD=new DatabaseConnection();

    public MonitorAgent()
    {}

    void CargarDatosIniciales() throws SQLException, NSClient4JException, ParseException, SigarException {
        System.out.println("Cargando Datos Iniciales");
        conexionBD.Conectar();
        RegistrarDatosIniciales();
        iniciarRegistroEnDB();
        System.out.println("Datos Iniciales Cargados Correctamente");
    }

    public void IniciarMonitoreo(int frecuency, int registerFrecuency,boolean continuarMon) throws IOException, InterruptedException, SQLException, ParseException, SigarException, NSClient4JException, InstantiationException, IllegalAccessException
    {
        System.out.println("Iniciando Monitoreo");
        continuarMonitoreo=continuarMon;
        //Frecuencia para creación de Logs o para envío de batch a la BD
        frecuency=frecuency*1000;
        //Frecuencia de registro en cada Log o de registro en batch
        registerFrecuency=registerFrecuency*1000;
        /* Generación de logs
         *
            String logName="LogMonitor"+new SimpleDateFormat(fmt1).format(new Date())+".log";
            fw=new FileWriter(logName);
            bw = new BufferedWriter(fw);
            salida = new PrintWriter(bw);
         *
        */
        for (int i=0; i<frecuency; i=i+registerFrecuency) {
            conexionBD.Conectar();
            //Registrar(salida);
            
            Registrar();
            //RegistrarCPU();
            Thread.sleep(registerFrecuency);
            contador=contador+1;
            iniciarRegistroEnDB();
        }
        //salida.close();
        if (continuarMonitoreo)
        {
            System.out.println("Continuando Monitoreo");
        }else{
            try {
                TerminarMonitoreo(true);
            } catch (Throwable ex) {
                Logger.getLogger(MonitorAgent.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    public void TerminarMonitoreo(boolean terminar) throws Throwable
    {
        if (terminar)
        {
            System.out.println("Terminando Monitoreo");
            super.finalize();
        }        
    }

    //En este metodo se realiza un registro Inicial de los datos generales del Nodo
    private void RegistrarDatosIniciales () throws SQLException, ParseException, NSClient4JException, SigarException
    {
             PhysicalMachine monitor=new PhysicalMachine();
             java.util.Date date;
             date=new Date();
             java.sql.Timestamp timest = new java.sql.Timestamp(date.getTime());
             UUID=java.util.UUID.randomUUID().toString();
             com.sun.security.auth.module.NTSystem NTSystem = new com.sun.security.auth.module.NTSystem();
             //Evalua una sola CPU
             org.hyperic.sigar.CpuInfo[] infos = this.sigar.getCpuInfoList();
             org.hyperic.sigar.CpuInfo CPU1 = infos[0];
             conexionBD.CargarBatchInicial(UUID,timest,monitor.network.getHostname(),NTSystem.getDomain(),monitor.operatingSystem.getOperatingSystemName(),
                     monitor.operatingSystem.getOperatingSystemVersion(),monitor.operatingSystem.getOperatingSystemArchitect(),monitor.cpu.getCPUModel(),
                     monitor.cpu.getCPUVendor(),monitor.cpu.getCPUCores(),CPU1.getTotalSockets(),monitor.cpu.getCPUMhz(),CPU1.getCoresPerSocket(),
                     monitor.memory.getRAMMemorySize(),monitor.memory.getSwapMemorySize(),monitor.hardDisk.getHardDiskSpace(),monitor.hardDisk.getHardDiskFileSystem(),
                     monitor.network.getNetworkMACAddress());
             //salida.flush();
    }

    //En este metodo se realiza un registro full de todos los parametros
    //private void Registrar(PrintWriter salida) throws SQLException
    public void Registrar () throws SQLException, ParseException, NSClient4JException, SigarException, InstantiationException, IllegalAccessException
    {
            //NSClient4j client = new NSClient4j("127.0.0.1",1248);
            //client.init();
            //System.out.println(client.isServiceUp("lanmanserver") + "/" + client.getUpTimeDate()+ "/" + client.getUpTimeDays()+ "/" + client.getUpTimeHours() + "/" + client.getUpTimeMinutes())
            //System.out.println(monitor.operatingSystem.logOut())
            //SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss.SSS");
            /*************/
            LocalProcessExecutor executor = new LocalProcessExecutor();
             String UserName = executor.executeCommandOutput("whoami",false).trim();
             LinpackJava.Linpack CPUMflops = new LinpackJava.Linpack();
             CPUMflops.run_benchmark();
             PhysicalMachine monitor=new PhysicalMachine();
             java.util.Date date;
             date=new Date();
             java.sql.Timestamp timest = new java.sql.Timestamp(date.getTime());
             Main.ContadorRegistros ++;
             Cpu CPU3 = this.sigar.getCpu();
             CpuPerc CPU2 = this.sigar.getCpuPerc();
             Uptime UPTIME = this.sigar.getUptime();
             Mem MEM =  this.sigar.getMem();
             NetInterfaceStat NET = this.sigar.getNetInterfaceStat(monitor.network.getNetworkInterface());
             conexionBD.CargarBatch(UUID,timest,Main.ContadorRegistros,UserName,UPTIME.getUptime(),CPUMflops.getMflops(),
                     CPUMflops.getTimeinSecs(),CPU2.getIdle()*100,(100-(CPU2.getIdle()*100)),CPU2.getUser()*100,CPU2.getSys()*100,CPU2.getNice()*100,
                     CPU2.getWait()*100,CPU2.getCombined()*100,CPU3.getUser(),CPU3.getSys(),CPU3.getNice(),CPU3.getWait(),CPU3.getIdle(),
                     monitor.memory.getRAMMemoryFree(),monitor.memory.getRAMMemoryUsed(),MEM.getFreePercent(),MEM.getUsedPercent(),
                     monitor.memory.getSwapMemoryFree(),monitor.memory.getSwapMemoryPageIn(),monitor.memory.getSwapMemoryPageOut(),
                     monitor.memory.getSwapMemoryUsed(),monitor.hardDisk.getHardDiskFreeSpace(),monitor.hardDisk.getHardDiskUsedSpace(),
                     monitor.network.getNetworkIPAddress(),monitor.network.getNetworkInterface(),monitor.network.getNetworkNetmask(),
                     monitor.network.getNetworkGateway(),NET.getRxBytes(),NET.getTxBytes(),NET.getSpeed(),NET.getRxErrors(),NET.getTxErrors(),
                     NET.getRxPackets(),NET.getTxPackets());

             //salida.flush();
    }

    //En este metodo se realiza un resgistro parcial de solo parametros de CPU
    private void RegistrarCPU () throws SQLException, ParseException, NSClient4JException, SigarException
    {
            System.out.println("Iniciando RegistrarCPU");
            PhysicalMachine monitor=new PhysicalMachine();
             java.util.Date date;
             date=new Date();
             java.sql.Timestamp timest = new java.sql.Timestamp(date.getTime());
             Main.ContadorRegistros ++;
             com.sun.security.auth.module.NTSystem NTSystem = new com.sun.security.auth.module.NTSystem();
             conexionBD.CargarBatchCPU(timest, NTSystem.getDomain(),NTSystem.getName(),monitor.network.getHostname(),
                     Main.ContadorRegistros, monitor.cpu.getCPUModel(),monitor.cpu.getCPUVendor(), monitor.cpu.getCPUCores(),
                     monitor.cpu.getCPUMhz(),monitor.cpu.getCPUidle(),monitor.cpu.getCPUUsed(),monitor.network.getNetworkIPAddress());
    }

    public static Timestamp getTodayTimestamp ()
    {
        Calendar calendar=Calendar.getInstance();
        Timestamp timeStamp = new Timestamp(calendar.getTimeInMillis());
        return timeStamp;
    }

    private void iniciarRegistroEnDB() throws SQLException
    {
        conexionBD.RegistrarBatch();
    }

    @Override
    public void output(String[] strings) throws SigarException {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}

